package com.aizuda.boot.modules.flw.service.impl;

import cn.hutool.core.thread.ThreadUtil;
import com.aizuda.boot.modules.business.contract.entity.ContractWorkflowEntity;
import com.aizuda.boot.modules.business.contract.entity.vo.WorkflowFormFieldsListDTO;
import com.aizuda.boot.modules.business.contract.mapper.ContractWorkflowMapper;
import com.aizuda.boot.modules.business.contract.service.impl.ContractExe;
import com.aizuda.boot.modules.business.feishu.service.FeiShuApprovalService;
import com.aizuda.boot.modules.business.negotiation.entity.ContractNegotiationConfigEntity;
import com.aizuda.boot.modules.business.negotiation.mapper.ContractNegotiationConfigMapper;
import com.aizuda.boot.modules.business.template.service.ContractTemplateService;
import com.aizuda.boot.modules.flw.entity.*;
import com.aizuda.boot.modules.flw.entity.dto.*;
import com.aizuda.boot.modules.flw.entity.vo.FlwFormTemplateDetailVO;
import com.aizuda.boot.modules.flw.entity.vo.FlwInstanceVO;
import com.aizuda.boot.modules.flw.entity.vo.FlwProcessCategoryVO;
import com.aizuda.boot.modules.flw.entity.vo.FlwProcessVO;
import com.aizuda.boot.modules.flw.flow.FlowForm;
import com.aizuda.boot.modules.flw.flow.FlowHelper;
import com.aizuda.boot.modules.flw.mapper.FlowlongMapper;
import com.aizuda.boot.modules.flw.service.*;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.aizuda.boot.modules.system.service.ISysDepartmentService;
import com.aizuda.boot.modules.system.entity.vo.DepartmentHeadVO;
import com.aizuda.bpm.engine.*;
import com.aizuda.bpm.engine.core.FlowCreator;
import com.aizuda.bpm.engine.core.FlowLongContext;
import com.aizuda.bpm.engine.core.enums.FlowState;
import com.aizuda.bpm.engine.core.enums.NodeSetType;
import com.aizuda.bpm.engine.core.enums.ProcessType;
import com.aizuda.bpm.engine.entity.*;
import com.aizuda.boot.modules.system.entity.SysUser;
import com.aizuda.bpm.engine.dao.FlwHisTaskDao;
import com.aizuda.bpm.engine.dao.FlwHisTaskActorDao;
import com.aizuda.bpm.engine.FlowLongIdGenerator;
import com.aizuda.bpm.engine.core.enums.TaskState;
import com.aizuda.bpm.engine.core.enums.TaskType;
import com.aizuda.bpm.engine.model.*;
import com.aizuda.bpm.mybatisplus.mapper.FlwProcessMapper;
import com.aizuda.common.toolkit.JacksonUtils;
import com.aizuda.core.api.ApiAssert;
import com.aizuda.service.web.UserSession;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.repository.AbstractRepository;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;
import com.aizuda.bpm.engine.model.NodeAssignee;
import com.aizuda.bpm.engine.model.ConditionNode;

/**
 * 流程分类 服务实现类
 *
 * @author 青苗
 * @since 2023-09-07
 */
@Slf4j
@Service
@AllArgsConstructor
public class FlwProcessServiceImpl extends ServiceImpl<FlwProcessMapper, FlwProcess> implements IFlwProcessService {
    private ProcessService processService;
    private IFlwProcessCategoryService flwProcessCategoryService;
    private IFlwProcessPermissionService flwProcessPermissionService;
    private IFlwProcessConfigureService flwProcessConfigureService;
    private IFlwProcessApprovalService flwProcessApprovalService;
    private IFlwProcessActorService flwProcessActorService;
    private IFlwProcessFormService flwProcessFormService;
    private IFlwFormTemplateService flwFormTemplateService;
    private FlowlongMapper flowlongMapper;
    private FlowLongEngine flowLongEngine;
    private ISysDepartmentService sysDepartmentService;

    @Resource
    private ContractExe contractExe;

    @Resource
    private ContractWorkflowMapper contractWorkflowMapper;

    @Resource
    private ContractNegotiationConfigMapper contractNegotiationConfigMapper;

    @Resource
    private ContractTemplateService contractTemplateService;

    @Resource
    private FeiShuApprovalService feiShuApprovalService;

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private FlwHisTaskDao hisTaskDao;
    
    @Resource
    private FlwHisTaskActorDao hisTaskActorDao;
    
    @Resource
    private FlowLongIdGenerator flowLongIdGenerator;

    @Override
    public Page<FlwProcess> pageHistory(Page<FlwProcess> page, FlwProcessHistoryDTO dto) {
        FlwProcess flwProcess = this.checkById(dto.getProcessId());
        LambdaQueryWrapper<FlwProcess> lqw = Wrappers.lambdaQuery();
        lqw.select(FlwProcess::getId, FlwProcess::getProcessName, FlwProcess::getProcessIcon,
                FlwProcess::getProcessVersion, FlwProcess::getRemark, FlwProcess::getCreateTime);
        // 历史流程
        lqw.eq(FlwProcess::getProcessState, 2);
        lqw.eq(FlwProcess::getProcessKey, flwProcess.getProcessKey());
        lqw.orderByDesc(FlwProcess::getProcessVersion);
        return super.page(page, lqw);
    }

    @Override
    public Page<FlwInstanceVO> pageInstance(Page<FlwInstanceVO> page, FlwProcessInstanceDTO dto) {
        if (null != dto) {
            if (null == dto.getCompleted()) {
                dto.setCompleted(false);
            }
        }
        return flowlongMapper.selectPageInstance(page, dto);
    }

    @Override
    public List<FlwProcessCategoryVO> listCategoryAll(String keyword) {
        return this.listCategoryVO(keyword, false);
    }

    public List<FlwProcessCategoryVO> listCategoryVO(String keyword, boolean launch) {
        List<FlwProcessCategory> categoryList = flwProcessCategoryService.list();
        if (CollectionUtils.isEmpty(categoryList)) {
            return null;
        }
        // 全部查询
        List<FlwProcessCategoryVO> voList = new ArrayList<>();
        List<FlwProcessVO> flwProcessVOList;
        if (launch) {
            flwProcessVOList = flowlongMapper.selectLaunchProcessList();
        } else {
            flwProcessVOList = flowlongMapper.selectFlwProcessList();
        }

        boolean voIsNotEmpty = CollectionUtils.isNotEmpty(flwProcessVOList);
        if (voIsNotEmpty) {
            boolean needSort = true;
            if (launch) {
                // 发起流程，过滤不存在角色权限的流程
                UserSession userSession = UserSession.getLoginInfo();
                List<Long> notExistProcessIds = flowlongMapper.selectNotExistProcessIds(userSession.getId());
                if (CollectionUtils.isNotEmpty(notExistProcessIds)) {
                    needSort = false;
                    flwProcessVOList = flwProcessVOList.stream().sorted(Comparator.comparing(FlwProcessVO::getProcessSort))
                            .filter(t -> !notExistProcessIds.contains(t.getProcessId())).toList();
                }
            }
            // 排序
            if (needSort) {
                flwProcessVOList.sort(Comparator.comparing(FlwProcessVO::getProcessSort));
            }
        }

        if (null == keyword) {
            // 不存在关键词查询
            for (FlwProcessCategory fpc : categoryList) {
                if (voIsNotEmpty) {
                    List<FlwProcessVO> processList = flwProcessVOList.stream().filter(f -> Objects.equals(fpc.getId(), f.getCategoryId())).toList();
                    boolean isEmpty = CollectionUtils.isEmpty(processList);
                    if (isEmpty && launch) {
                        continue;
                    }
                    FlwProcessCategoryVO vo = FlwProcessCategoryVO.of(fpc);
                    vo.setProcessList(processList);
                    voList.add(vo);
                } else if (!launch) {
                    // 非发起列表情况
                    voList.add(FlwProcessCategoryVO.of(fpc));
                }
            }
        } else {
            // 关键词查询
            for (FlwProcessCategory fpc : categoryList) {
                if (voIsNotEmpty) {
                    List<FlwProcessVO> processList = flwProcessVOList.stream().filter(t -> Objects.equals(t.getCategoryId(), fpc.getId())
                            && t.getProcessName().contains(keyword)).toList();
                    if (fpc.getName().contains(keyword)) {
                        // 匹配分类名称
                        if (CollectionUtils.isEmpty(processList)) {
                            if (launch) {
                                continue;
                            }
                            FlwProcessCategoryVO vo = FlwProcessCategoryVO.of(fpc);
                            vo.setProcessList(flwProcessVOList.stream().filter(f -> Objects.equals(f.getCategoryId(), fpc.getId())).toList());
                            voList.add(vo);
                        } else {
                            FlwProcessCategoryVO vo = FlwProcessCategoryVO.of(fpc);
                            vo.setProcessList(processList);
                            voList.add(vo);
                        }
                    } else if (CollectionUtils.isNotEmpty(processList)) {
                        // 匹配流程定义
                        FlwProcessCategoryVO vo = FlwProcessCategoryVO.of(fpc);
                        vo.setProcessList(processList);
                        voList.add(vo);
                    }
                } else if (!launch) {
                    // 非发起列表情况
                    voList.add(FlwProcessCategoryVO.of(fpc));
                }
            }
        }
        return voList;
    }

    @Override
    public List<FlwProcessCategoryVO> listLaunch(String keyword) {
        return this.listCategoryVO(keyword, true);
    }

    @Override
    public List<FlwProcess> listChildTop10(String keyword) {
        // 查询正常状态的子流程
        return lambdaQuery().select(FlwProcess::getId, FlwProcess::getProcessName)
                .like(StringUtils.isNotEmpty(keyword), FlwProcess::getProcessName, keyword)
                .eq(FlwProcess::getProcessType, ProcessType.child)
                .eq(FlwProcess::getProcessState, 1)
                .orderByDesc(FlwProcess::getCreateTime).last("LIMIT 10").list();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long launchProcess(ProcessStartDTO dto, FlowCreator flowCreator) {
        FlwProcess flwProcess = flowLongEngine.processService().getProcessById(dto.getProcessId());
        ApiAssert.fail(null == flwProcess, "指定流程模型不存在");

        // 获取未设置处理人员节点
        final Map<String, DynamicAssignee> assigneeMap = dto.getAssigneeMap();
        List<NodeModel> unsetAssigneeNodes = ModelHelper.getUnsetAssigneeNodes(flwProcess.model(true).getNodeConfig());
        if (CollectionUtils.isNotEmpty(unsetAssigneeNodes)) {
            unsetAssigneeNodes.forEach(t -> {
                if (NodeSetType.supervisor.eq(t.getSetType()) || NodeSetType.multiLevelSupervisors.eq(t.getSetType())) {
                    // 主管由 FlowTaskActorProvider 类提供，不认为非法逻辑
                    return;
                }

                final DynamicAssignee dynamicAssignee = assigneeMap.get(t.getNodeKey());
                if (NodeSetType.specifyMembers.eq(t.getSetType()) || NodeSetType.initiatorSelected.eq(t.getSetType())) {
                    ApiAssert.fail(null == dynamicAssignee, "发起人自选节点未设置处理人员");
                }
                ApiAssert.fail(null == dynamicAssignee || CollectionUtils.isEmpty(dynamicAssignee.getAssigneeList()),
                        "节点【 " + t.getNodeName() + " 】未设置处理人员");
            });
        }
        // 传递动态分配处理人员
        if (null != assigneeMap) {
            FlowDataTransfer.dynamicAssignee(Collections.unmodifiableMap(assigneeMap));
        }

        // 传递表单参数
        FlowForm.argsTransfer(dto.getProcessForm());

        // 启动流程
        Optional<FlwInstance> opt = flowLongEngine.startInstanceById(dto.getProcessId(), flowCreator, null, dto.isSaveAsDraft(), () -> {
            FlwInstance flwInstance = new FlwInstance();
            flwInstance.setBusinessKey(dto.getBusinessKey());
            return flwInstance;
        });
        ApiAssert.fail(opt.isEmpty(), "流程启动失败");

        // 保存表单
        FlwInstance flwInstance = opt.get();
        ApiAssert.fail(!flwProcessFormService.saveForm(flwInstance.getId(), dto.getProcessForm()), "保存保单失败");
        
        // 创建抄送任务给流程中所有审批人
        try {
            createCopyTasksForAllUsers(flwInstance.getId(), flwProcess, flowCreator);
        } catch (Exception e) {
            log.warn("创建抄送任务失败: {}", e.getMessage(), e);
        }
        
        return flwInstance.getId();
    }

    @Override
    public Map<String, Object> getVariableByInstanceId(Long instanceId) {
        QueryService queryService = flowLongEngine.queryService();
        FlwInstance fi = queryService.getInstance(instanceId);
        if (null != fi) {
            return fi.variableToMap();
        }

        // 已完成流程
        FlwHisInstance fhi = queryService.getHistInstance(instanceId);
        if (null != fhi) {
            return fhi.variableToMap();
        }

        // 不存在情况
        return new HashMap<>();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeProcessByInstanceIds(List<Long> instanceIds) {
        for (Long instanceId : instanceIds) {
            FlwHisInstance fhi = flowLongEngine.queryService().getHistInstance(instanceId);
            if (null != fhi) {
                ApiAssert.fail(fhi.getInstanceState() > 0, "流程已执行结束不允许删除");
                flowLongEngine.runtimeService().cascadeRemoveByInstanceId(instanceId);
            }
        }
        return true;
    }

    @Override
    public boolean resumeProcessByInstanceId(Long instanceId) {
        return flowLongEngine.taskService().resume(instanceId, FlowHelper.getFlowCreator());
    }


    @Override
    public boolean terminateProcessByInstanceId(Long instanceId) {
        return flowLongEngine.runtimeService().terminate(instanceId, FlowHelper.getFlowCreator());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean destroyProcessByInstanceId(DestroyInstanceDTO dto) {
        if (StringUtils.isNoneBlank(dto.getOpinion())) {
            FlwProcessApproval fpa = new FlwProcessApproval();
            fpa.setInstanceId(dto.getInstanceId());
            fpa.setType(16);
            ApprovalContent content = new ApprovalContent();
            content.setOpinion(dto.getOpinion());
            fpa.setContent(content);
            flwProcessApprovalService.save(fpa);
        }
        return flowLongEngine.runtimeService().destroyByInstanceId(dto.getInstanceId(), null);
    }

    @Override
    public String getNodeModelById(Long id) {
        FlwProcess flwProcess = this.checkById(id);
        return flwProcess.getModelContent();
    }

    @Override
    public FlwProcessDTO getDtoById(Long id) {
        return getFlwProcessDTO(this.checkById(id));
    }

    public FlwProcessDTO getFlwProcessDTO(FlwProcess flwProcess) {
        ApiAssert.isEmpty(flwProcess, "未发现指定流程模型");
        FlwProcessDTO dto = FlwProcessDTO.of(flwProcess);
        // 流程权限
        List<FlwProcessPermission> permissionList = flwProcessPermissionService.getByProcessId(flwProcess.getId());
        if (CollectionUtils.isNotEmpty(permissionList)) {
            dto.setProcessPermissionList(permissionList.stream().map(FlwProcessPermissionDTO::of).toList());
        }
        // 流程配置
        FlwProcessConfigure configure = flwProcessConfigureService.getByProcessId(flwProcess.getId());
        if (null != configure) {
            dto.setCategoryId(configure.getCategoryId());
            dto.setProcessSetting(configure.getProcessSetting());
            if (ProcessType.business.eq(flwProcess.getProcessType())) {
                dto.setBusinessForm(configure.getProcessForm());
//                 加载表单模板内容
                dto.setFormTemplate(flwFormTemplateService.getByConfigure(configure.getProcessForm()));
            } else {
                dto.setProcessForm(configure.getProcessForm());
            }
        }
        return dto;
    }

    @Override
    public FlwProcessDTO getDtoByKey(String key) {
        return getFlwProcessDTO(baseMapper.selectOne(Wrappers.<FlwProcess>lambdaQuery()
                .eq(FlwProcess::getProcessKey, key).eq(FlwProcess::getProcessState, 1)));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long saveDto(FlwProcessDTO dto) {
        ApiAssert.fail(null == dto.getCategoryId(), "流程定义分类ID不存在");
        ProcessModel processModel = ModelHelper.buildProcessModel(dto.getModelContent());
        NodeModel rootNode = processModel.getNodeConfig();
        int checkNodeModel = ModelHelper.checkNodeModel(rootNode);
        if (checkNodeModel > 0) {
            ApiAssert.equals(1, checkNodeModel, "模型节点名称不允许重复");
            ApiAssert.equals(2, checkNodeModel, "自动通过节点配置错误，请确保包含在条件分支节点中");
            ApiAssert.equals(3, checkNodeModel, "自动拒绝节点配置错误，请确保包含在条件分支节点中");
            ApiAssert.equals(4, checkNodeModel, "路由节点必须配置错误，请确保配置路由分支");
            ApiAssert.equals(5, checkNodeModel, "子流程节点配置错误，请确保已选择子流程");
            ApiAssert.equals(6, checkNodeModel, "抄送节点配置错误，请配置处理人或允许抄送自选");
        }
        ApiAssert.fail(null == rootNode.getChildNode(), "必须存在两个以上节点");
        int checkConditionNode = ModelHelper.checkConditionNode(rootNode);
        if (checkConditionNode > 0) {
            ApiAssert.equals(1, checkConditionNode, "存在多个条件表达式为空");
            ApiAssert.equals(2, checkConditionNode, "存在多个条件子节点为空");
            ApiAssert.equals(3, checkConditionNode, "存在条件节点KEY重复");
        }
        ApiAssert.fail(!ModelHelper.checkExistApprovalNode(rootNode), "必须存在审批节点");

        // 检查流程定义操作权限
        if (null != dto.getProcessId()) {
            this.checkOperateApproval(dto.getProcessId());
        }

        // 检查流程定义KEY唯一性
        this.checkProcessKey(dto.getProcessId(), dto.getProcessKey());

        // 部署流程定义，修改会产生历史流程
        final Long processId = processService.deploy(dto.getProcessId(), dto.getModelContent(),
                FlowHelper.getFlowCreator(), true, flwProcess -> {
                    // 流程图标
                    flwProcess.setProcessIcon(dto.getProcessIcon());

                    // 流程类型
                    flwProcess.setProcessType(dto.getProcessType());

                    // 创建 0 不可用状态，需要发布后才可以使用
                    flwProcess.setFlowState(FlowState.inactive);

                    // 备注说明
                    flwProcess.setRemark(dto.getRemark());
                });

        // 流程定义权限
        List<FlwProcessPermissionDTO> processPermissionList = dto.getProcessPermissionList();
        if (CollectionUtils.isNotEmpty(processPermissionList)) {
            ApiAssert.fail(!flwProcessPermissionService.saveProcessPermissions(processId, processPermissionList),
                    "流程定义管理权限保存失败");
        }

        // 设置流程定义参与者，限制发起人角色
        List<NodeAssignee> nodeAssigneeList = rootNode.getNodeAssigneeList();
        if (CollectionUtils.isNotEmpty(nodeAssigneeList)) {
            ApiAssert.fail(!flwProcessActorService.saveProcessActors(processId, nodeAssigneeList.stream().map(t -> {
                FlwProcessActor fpa = new FlwProcessActor();
                fpa.setProcessId(processId);
                // 暂时支持角色限制
                fpa.setActorType(0);
                fpa.setActorId(Long.valueOf(t.getId()));
                fpa.setActorName(t.getName());
                return fpa;
            }).toList()), "流程发起人参与者信息保持失败");
        }

        // 保存流程定义配置
        if (null != dto.getCategoryId()) {
            ApiAssert.fail(!flwProcessConfigureService.saveByDto(processId, dto), "流程定义配置保存失败");
        }

        return processId;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long saveDtoNew(FlwProcessDTO dto) {
        ApiAssert.fail(null == dto.getCategoryId(), "流程定义分类ID不存在");


        ProcessModel processModel = ModelHelper.buildProcessModel(dto.getModelContent());
        NodeModel rootNode = processModel.getNodeConfig();
        int checkNodeModel = ModelHelper.checkNodeModel(rootNode);
        if (checkNodeModel > 0) {
            ApiAssert.equals(1, checkNodeModel, "模型节点名称不允许重复");
            ApiAssert.equals(2, checkNodeModel, "自动通过节点配置错误，请确保包含在条件分支节点中");
            ApiAssert.equals(3, checkNodeModel, "自动拒绝节点配置错误，请确保包含在条件分支节点中");
            ApiAssert.equals(4, checkNodeModel, "路由节点必须配置错误，请确保配置路由分支");
            ApiAssert.equals(5, checkNodeModel, "子流程节点配置错误，请确保已选择子流程");
        }
        ApiAssert.fail(null == rootNode.getChildNode(), "必须存在两个以上节点");
        int checkConditionNode = ModelHelper.checkConditionNode(rootNode);
        if (checkConditionNode > 0) {
            ApiAssert.equals(1, checkConditionNode, "存在多个条件表达式为空");
            ApiAssert.equals(2, checkConditionNode, "存在多个条件子节点为空");
            ApiAssert.equals(3, checkConditionNode, "存在条件节点KEY重复");
        }
        ApiAssert.fail(!ModelHelper.checkExistApprovalNode(rootNode), "必须存在审批节点");

        // 检查流程定义操作权限
        if (null != dto.getProcessId()) {
            this.checkOperateApproval(dto.getProcessId());
        }

        // 检查流程定义KEY唯一性
        this.checkProcessKey(dto.getProcessId(), dto.getProcessKey());

        if (Objects.equals(dto.getProcessType(), "business") && null != dto.getFormTemplate()) {
            FlwFormTemplate formTemplate = dto.getFormTemplate();
            FlwFormTemplateDetailVO vo = formTemplate.convert(FlwFormTemplateDetailVO.class);
            String content = vo.getContent();
            Map map = JSON.parseObject(content, Map.class);
            // 修复类型转换错误：使用正确的方式将JSONArray转换为WorkflowFormFieldsListDTO列表
            Object schemasObject = map.get("schemas");
            List<WorkflowFormFieldsListDTO> list = null;
            if (schemasObject instanceof List) {
                list = JSON.parseArray(JSON.toJSONString(schemasObject), WorkflowFormFieldsListDTO.class);
            }
            vo.setFormFields(list);
            ApiAssert.fail(!flwFormTemplateService.updateByIdNew(vo), "表单保存失败");
        } else if (Objects.equals(dto.getProcessType(), "business")) {
            FlwFormTemplate template = new FlwFormTemplate();
            template.setFormCategoryId(0L);
            template.setName(UUID.randomUUID().toString().replace("-", "").substring(0, 32));
            template.setContent(dto.getProcessForm());
            template.setCode(UUID.randomUUID().toString().replace("-", "").substring(0, 32));
            template.setType(0);
            template.setStatus(1);
            template.setSort(1);
            // 设置租户ID，避免数据库约束错误
            template.setTenantId("default");
            flwFormTemplateService.save(template);
            FlwFormTemplateDetailVO vo = template.convert(FlwFormTemplateDetailVO.class);
            Map map = JSON.parseObject(dto.getProcessForm(), Map.class);
            // 修复类型转换错误：使用正确的方式将JSONArray转换为WorkflowFormFieldsListDTO列表
            Object schemasObject = map.get("schemas");
            List<WorkflowFormFieldsListDTO> list = null;
            if (schemasObject instanceof List) {
                list = JSON.parseArray(JSON.toJSONString(schemasObject), WorkflowFormFieldsListDTO.class);
            }
            vo.setFormFields(list);
            ApiAssert.fail(!flwFormTemplateService.updateByIdNew(vo), "表单保存失败");
            Map<String, String> FormMap = new HashMap<>();
            FormMap.put("formId", String.valueOf(template.getId()));
            FormMap.put("formName", template.getName());
            dto.setBusinessForm(JacksonUtils.toJson(FormMap));
        }

        // 部署流程定义，修改会产生历史流程
        final Long processId = processService.deploy(dto.getProcessId(), dto.getModelContent(),
                FlowHelper.getFlowCreator(), true, flwProcess -> {
                    // 流程图标
                    flwProcess.setProcessIcon(dto.getProcessIcon());

                    // 流程类型
                    flwProcess.setProcessType(dto.getProcessType());

                    // 创建 0 不可用状态，需要发布后才可以使用
                    flwProcess.setFlowState(FlowState.inactive);

                    // 备注说明
                    flwProcess.setRemark(dto.getRemark());
                });

        // 流程定义权限
        List<FlwProcessPermissionDTO> processPermissionList = dto.getProcessPermissionList();
        if (CollectionUtils.isNotEmpty(processPermissionList)) {
            ApiAssert.fail(!flwProcessPermissionService.saveProcessPermissions(processId, processPermissionList),
                    "流程定义管理权限保存失败");
        }

        // 设置流程定义参与者，限制发起人角色
        List<NodeAssignee> nodeAssigneeList = rootNode.getNodeAssigneeList();
        if (CollectionUtils.isNotEmpty(nodeAssigneeList)) {
            ApiAssert.fail(!flwProcessActorService.saveProcessActors(processId, nodeAssigneeList.stream().map(t -> {
                FlwProcessActor fpa = new FlwProcessActor();
                fpa.setProcessId(processId);
                // 暂时支持角色限制
                fpa.setActorType(0);
                fpa.setActorId(Long.valueOf(t.getId()));
                fpa.setActorName(t.getName());
                return fpa;
            }).toList()), "流程发起人参与者信息保持失败");
        }

        // 保存流程定义配置
        if (null != dto.getCategoryId()) {
            ApiAssert.fail(!flwProcessConfigureService.saveByDto(processId, dto), "流程定义配置保存失败");
        }
        try {
            if (processId != null) {
                log.info("流程创建成功，开始检查并更新相关模板content，processId: {}", processId);
                contractTemplateService.updateTemplateContentByProcessId(processId);
            }
        } catch (Exception e) {
            log.error("更新模板content失败，但不影响流程创建，processId: {}", processId, e);
        }
        FlowCreator flowCreator = FlowHelper.getFlowCreator();

        ThreadUtil.execute(() -> {
            // 同步飞书定义到飞书
            feiShuApprovalService.createProcess(processId, flowCreator);
        });

        return processId;
    }

    /**
     * 验证判断非历史版本流程流程唯一标识key
     */
    private void checkProcessKey(Long processId, String processKey) {
        Long count = lambdaQuery().ne(null != processId, FlwProcess::getId, processId)
                .ne(FlwProcess::getProcessState, 2)
                .eq(FlwProcess::getProcessKey, processKey).count();
        ApiAssert.fail(count > 0, "流程唯一标识key不允许重复");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeProcessInfo(Long id) {
        // 检查流程定义操作权限
        this.checkOperateApproval(id);

        // 删除流程
        FlwProcess flwProcess = this.checkById(id);
        long count = contractWorkflowMapper.selectCount(Wrappers.<ContractWorkflowEntity>lambdaQuery()
                .eq(ContractWorkflowEntity::getProcessKey, flwProcess.getProcessKey())) +
                contractNegotiationConfigMapper.selectCount(Wrappers.<ContractNegotiationConfigEntity>lambdaQuery()
                        .eq(ContractNegotiationConfigEntity::getProcessKey, flwProcess.getProcessKey()));
        if (count > 0) {
            ApiAssert.fail("流程定义正在使用中，请先停止使用");
        }
        if (Objects.equals(1, flwProcess.getProcessVersion())) {
            this.cascadeRemoveById(flwProcess.getId());
        } else {
            // 存在历史全部删除
            baseMapper.selectListByProcessKey(null,
                    flwProcess.getProcessKey()).forEach(t -> this.cascadeRemoveById(t.getId()));
        }
        return true;
    }

    private void cascadeRemoveById(Long id) {
        // 删除相关流程定义信息
        flwProcessActorService.removeByProcessId(id);
        flwProcessPermissionService.removeByProcessId(id);
        flwProcessConfigureService.removeByProcessId(id);
        // 级联删除相关信息
        flowLongEngine.processService().cascadeRemove(id);
    }

    private void checkOperateApproval(Long processId) {
        UserSession userSession = UserSession.getLoginInfo();
        if (null == userSession || !UserSession.isAdmin(userSession.getId())) {
            FlwProcessPermission fpp = getFlwProcessPermissionByProcessId(userSession, processId);
            if (null != fpp) {
                ApiAssert.fail(!fpp.allowOperateApproval(), "无权限编辑操作审批流程");
            }
        }
    }

    protected FlwProcessPermission getFlwProcessPermissionByProcessId(UserSession userSession, Long processId) {
        Long userId = null == userSession ? null : userSession.getId();
        return flwProcessPermissionService.getByUserIdAndProcessId(userId, processId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean sort(List<FlwCategorySortDTO> dtoList) {
        if (CollectionUtils.isNotEmpty(dtoList)) {
            int i = 0;
            List<FlwProcessCategory> fpcList = new ArrayList<>();
            List<FlwProcess> fpList = new ArrayList<>();
            for (FlwCategorySortDTO dto : dtoList) {
                List<Long> processIds = dto.getProcessIds();
                if (CollectionUtils.isNotEmpty(processIds)) {
                    int j = 0;
                    fpcList.add(dto.toFlwProcessCategory(++i));
                    for (Long processId : processIds) {
                        FlwProcess fp = new FlwProcess();
                        fp.setId(processId);
                        fp.setSort(++j);
                        fpList.add(fp);
                    }
                }
            }
            // 更新流程排序
            if (CollectionUtils.isNotEmpty(fpList)) {
                flwProcessConfigureService.updateRelation(dtoList);
                ApiAssert.fail(!super.updateBatchById(fpList), "流程顺序保存失败");
            }
            // 更新流程分类顺序
            if (CollectionUtils.isNotEmpty(fpcList)) {
                ApiAssert.fail(!flwProcessCategoryService.sort(fpcList), "流程分类顺序保存失败");
            }
        }
        return true;
    }

    @Override
    public boolean updateSateById(Long id, Integer state) {
        // 检查流程定义操作权限
        this.checkOperateApproval(id);

        FlwProcess process = this.getById(id);
        if (null == process || Objects.equals(2, process.getProcessState())){
            ApiAssert.fail("流程不存在或已有新版本发布！");
        }

        // 更新流程定义排序
        FlwProcess flwProcess = new FlwProcess();
        flwProcess.setId(id);
        int dbState = 0;
        if (Objects.equals(1, state)) {
            dbState = 1;
            // 删除缓存
            FlowLongContext.invalidateProcessModel(flwProcess.modelCacheKey());
        }
        flwProcess.setProcessState(dbState);
        return super.updateById(flwProcess);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean cloneById(Long id) {
        // 检查流程定义操作权限
        this.checkOperateApproval(id);

        // 克隆流程
        String suffix = "Copy" + System.currentTimeMillis();
        FlwProcessDTO dto = this.getDtoById(id);
        dto.setProcessId(null);
        dto.setProcessName(dto.getProcessName() + suffix);
        dto.setProcessKey(dto.getProcessKey() + suffix);
        dto.setProcessType(dto.getProcessType());
        String modelContent = dto.getModelContent();
        Map<String, Object> modelContentMap = JacksonUtils.readMap(modelContent);
        modelContentMap.put("name", dto.getProcessName());
        modelContentMap.put("key", dto.getProcessKey());
        dto.setModelContent(JacksonUtils.toJson(modelContentMap));
        return null != this.saveDto(dto);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean checkoutById(Long id) {
        // 检查流程定义操作权限
        this.checkOperateApproval(id);

        // 检出历史流程
        FlwProcess flwProcess = this.checkById(id);
        final int hisVersion = flwProcess.getProcessVersion();
        FlwProcess currentProcess = lambdaQuery().eq(FlwProcess::getProcessKey, flwProcess.getProcessKey())
                .ne(FlwProcess::getProcessState, 2).one();
        if (null != currentProcess) {
            // 启用历史流程，设置为当前版本
            FlwProcess temp = new FlwProcess();
            temp.setId(flwProcess.getId());
            temp.setProcessVersion(currentProcess.getProcessVersion());
            temp.setProcessState(currentProcess.getProcessState());
            if (super.updateById(temp)) {
                // 当前流程归档为历史状态
                FlwProcess his = new FlwProcess();
                his.setId(currentProcess.getId());
                his.setProcessVersion(hisVersion);
                his.setFlowState(FlowState.history);
                return super.updateById(his);
            }
        }
        return false;
    }

    @Override
    public List<FlwProcessCategoryVO> getBusinessProcess() {
        List<FlwProcessCategory> categoryList = flwProcessCategoryService.list();
        if (CollectionUtils.isEmpty(categoryList)) {
            return null;
        }
        // 全部查询
        List<FlwProcessCategoryVO> voList = new ArrayList<>();
        List<FlwProcessVO> flwProcessVOList = flowlongMapper.selectBussinessFlwProcessList(ProcessType.business.name());


        boolean voIsNotEmpty = CollectionUtils.isNotEmpty(flwProcessVOList);
        if (voIsNotEmpty) {
            boolean needSort = true;
            // 排序
            if (needSort) {
                flwProcessVOList.sort(Comparator.comparing(FlwProcessVO::getProcessSort));
            }
        }

        // 不存在关键词查询
        for (FlwProcessCategory fpc : categoryList) {
            if (voIsNotEmpty) {
                List<FlwProcessVO> processList = flwProcessVOList.stream().filter(f -> Objects.equals(fpc.getId(), f.getCategoryId())).toList();
                boolean isEmpty = CollectionUtils.isEmpty(processList);
                if (isEmpty) {
                    continue;
                }
                FlwProcessCategoryVO vo = FlwProcessCategoryVO.of(fpc);
                vo.setProcessList(processList);
                voList.add(vo);
            }
        }
        return voList;
    }

    @Override
    public List<FlwProcessCategoryVO> getChildProcess() {
        List<FlwProcessCategory> categoryList = flwProcessCategoryService.list();
        if (CollectionUtils.isEmpty(categoryList)) {
            return null;
        }
        // 全部查询
        List<FlwProcessCategoryVO> voList = new ArrayList<>();
        List<FlwProcessVO> flwProcessVOList = flowlongMapper.selectBussinessFlwProcessList(ProcessType.business_audit.name());


        boolean voIsNotEmpty = CollectionUtils.isNotEmpty(flwProcessVOList);
        if (voIsNotEmpty) {
            boolean needSort = true;
            // 排序
            if (needSort) {
                flwProcessVOList.sort(Comparator.comparing(FlwProcessVO::getProcessSort));
            }
        }

        // 不存在关键词查询
        for (FlwProcessCategory fpc : categoryList) {
            if (voIsNotEmpty) {
                List<FlwProcessVO> processList = flwProcessVOList.stream().filter(f -> Objects.equals(fpc.getId(), f.getCategoryId())).toList();
                boolean isEmpty = CollectionUtils.isEmpty(processList);
                if (isEmpty) {
                    continue;
                }
                FlwProcessCategoryVO vo = FlwProcessCategoryVO.of(fpc);
                vo.setProcessList(processList);
                voList.add(vo);
            }
        }
        return voList;
    }

    @Override
    public boolean saveBatch(Collection<FlwProcess> entityList) {
        return super.saveBatch(entityList, 100);
    }

    @Override
    public Map<String, Object> parseAssigneeMap(Long processId) {
        FlwProcess flwProcess = flowLongEngine.processService().getProcessById(processId);
        ApiAssert.fail(null == flwProcess, "指定流程模型不存在");

        // 解析流程模型
        ProcessModel processModel = flwProcess.model(true);
        NodeModel rootNode = processModel.getNodeConfig();

        Map<String, Object> assigneeMap = new HashMap<>();

        // 递归解析所有节点，提取审批人信息
        parseNodeAssignees(rootNode, assigneeMap);

        return assigneeMap;
    }

    /**
     * 递归解析节点审批人信息
     */
    private void parseNodeAssignees(NodeModel nodeModel, Map<String, Object> assigneeMap) {
        if (nodeModel == null) {
            return;
        }

        // 检查当前节点是否有审批人配置
        if (nodeModel.getNodeAssigneeList() != null && !nodeModel.getNodeAssigneeList().isEmpty()) {
            Map<String, Object> nodeAssignee = new HashMap<>();

            // 根据节点类型确定type值
            Integer type = determineAssigneeType(nodeModel);
            nodeAssignee.put("type", type);

            // 构造assigneeList
            List<Map<String, Object>> assigneeList = new ArrayList<>();
            for (NodeAssignee assignee : nodeModel.getNodeAssigneeList()) {
                Map<String, Object> assigneeInfo = new HashMap<>();
                assigneeInfo.put("id", assignee.getId());
                assigneeInfo.put("name", assignee.getName());
                if (assignee.getWeight() != null) {
                    assigneeInfo.put("weight", assignee.getWeight());
                }
                if (assignee.getTenantId() != null) {
                    assigneeInfo.put("tenantId", assignee.getTenantId());
                }
                // 添加扩展配置（包含头像等信息）
                if (assignee.getExtendConfig() != null) {
                    assigneeInfo.put("extendConfig", assignee.getExtendConfig());
                }
                assigneeList.add(assigneeInfo);
            }
            nodeAssignee.put("assigneeList", assigneeList);

            assigneeMap.put(nodeModel.getNodeKey(), nodeAssignee);
        }

        // 递归处理子节点
        NodeModel childNode = nodeModel.getChildNode();
        if (childNode != null) {
            parseNodeAssignees(childNode, assigneeMap);
        }

        // 处理条件分支节点
        if (nodeModel.getConditionNodes() != null) {
            for (ConditionNode conditionNode : nodeModel.getConditionNodes()) {
                NodeModel conditionChildNode = conditionNode.getChildNode();
                parseNodeAssignees(conditionChildNode, assigneeMap);
            }
        }

        // 处理并行分支节点
        if (nodeModel.getParallelNodes() != null) {
            for (ConditionNode parallelNode : nodeModel.getParallelNodes()) {
                NodeModel parallelChildNode = parallelNode.getChildNode();
                parseNodeAssignees(parallelChildNode, assigneeMap);
            }
        }

        // 处理包容分支节点
        if (nodeModel.getInclusiveNodes() != null) {
            for (ConditionNode inclusiveNode : nodeModel.getInclusiveNodes()) {
                NodeModel inclusiveChildNode = inclusiveNode.getChildNode();
                parseNodeAssignees(inclusiveChildNode, assigneeMap);
            }
        }
    }

    /**
     * 根据节点配置确定审批人类型
     */
    private Integer determineAssigneeType(NodeModel nodeModel) {
        if (nodeModel.getSetType() == null) {
            return 1; // 默认用户类型
        }

        String setType = nodeModel.getSetType().toString();
        switch (setType) {
            case "role":
                return 3; // 角色类型
            case "department":
                return 2; // 部门类型
            case "specifyMembers":
            case "initiatorSelected":
                // 根据选择模式确定类型
                if (nodeModel.getSelectMode() != null && nodeModel.getSelectMode() == 3) {
                    return 3; // 角色
                } else {
                    return 1; // 用户
                }
            default:
                return 1; // 默认用户类型
        }
    }

    @Override
    public Map<String, Object> getNegotiation(Long processId) {
        // 获取assigneeMap
        Map<String, Object> assigneeMap = parseAssigneeMap(processId);

        // 获取流程信息和processForm
        FlwProcessDTO processDTO = getDtoById(processId);
        String processForm = processDTO.getProcessForm();

        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("assigneeMap", assigneeMap);
        result.put("processForm", processForm);

        return result;
    }

    @Override
    public boolean removeProcessInfoNew(Long id) {
        // 检查流程定义操作权限
        this.checkOperateApproval(id);

        // 删除流程
        FlwProcess flwProcess = this.checkById(id);
        long count = contractWorkflowMapper.selectCount(Wrappers.<ContractWorkflowEntity>lambdaQuery()
                .eq(ContractWorkflowEntity::getProcessKey, flwProcess.getProcessKey())) +
                contractNegotiationConfigMapper.selectCount(Wrappers.<ContractNegotiationConfigEntity>lambdaQuery()
                        .eq(ContractNegotiationConfigEntity::getProcessKey, flwProcess.getProcessKey()));
        if (count > 0) {
            ApiAssert.fail("流程定义正在使用中，请先停止使用");
        }
        if (flwProcess.getProcessType().equals("business")) {
            FlwProcessConfigure configure = flwProcessConfigureService.getOne(Wrappers.<FlwProcessConfigure>lambdaQuery()
                    .eq(FlwProcessConfigure::getProcessId, id)
                    .last("limit 1"));
            String formId = (String) JSON.parseObject(configure.getProcessForm(), Map.class).get("formId");
            flwFormTemplateService.removeNotBindByIdsNew(Collections.singletonList(Long.parseLong(formId)));
        }
        if (Objects.equals(1, flwProcess.getProcessVersion())) {
            this.cascadeRemoveById(flwProcess.getId());
        } else {
            // 存在历史全部删除
            baseMapper.selectListByProcessKey(null,
                    flwProcess.getProcessKey()).forEach(t -> this.cascadeRemoveById(t.getId()));
        }
        return true;
    }
    
    /**
     * 为流程中所有审批人创建抄送任务
     */
    private void createCopyTasksForAllUsers(Long instanceId, FlwProcess flwProcess, FlowCreator flowCreator) {
        try {
            // 获取流程模型的根节点
            NodeModel rootNodeModel = flwProcess.model(true).getNodeConfig();
            if (rootNodeModel == null) {
                return;
            }
            
            // 收集所有活动任务的审批人和主管信息
            Set<String> allUserIds = new HashSet<>();
            collectAllAssignees(instanceId, allUserIds);
            
            // 打印收集到的所有用户ID
            log.info("=== 抄送任务用户ID收集结果 ===");
            log.info("流程实例ID: {}", instanceId);
            log.info("收集到的用户ID数量: {}", allUserIds.size());
            log.info("收集到的用户ID列表: {}", allUserIds);
            
            if (allUserIds.isEmpty()) {
                log.warn("未收集到任何用户ID，跳过抄送任务创建");
                return;
            }
            
            // 转换为Long类型的用户ID列表
            List<Long> userIds = allUserIds.stream()
                .map(Long::valueOf)
                .collect(Collectors.toList());
            
            log.info("转换后的Long类型用户ID列表: {}", userIds);
            
            // 获取当前登录用户信息
            UserSession loginInfo = UserSession.getLoginInfo();
            
            // 自己实现抄送任务创建逻辑
            createCopyTaskInternal(instanceId, userIds, loginInfo);
            
        } catch (Exception e) {
            log.error("创建抄送任务失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 内部实现抄送任务创建逻辑
     */
    private void createCopyTaskInternal(Long instanceId, List<Long> userIds, UserSession loginInfo) {
        try {
            // 1. 直接构造历史任务对象
            FlwHisTask hisTask = new FlwHisTask();
            hisTask.setId(flowLongIdGenerator.getId(hisTask.getId()));
            hisTask.setInstanceId(instanceId);
            hisTask.setCreateId(loginInfo.getUserId().toString());
            hisTask.setCreateBy(loginInfo.getUsername());
            hisTask.setCreateTime(new Date());
            hisTask.setTaskName("抄送任务");
            hisTask.setTaskKey("copy_task");
            hisTask.setTaskType(TaskType.cc.getValue());
            hisTask.setTaskState(TaskState.complete.getValue());
            hisTask.setFinishTime(new Date());
            hisTask.calculateDuration();
            
            // 2. 插入历史任务
            if (!hisTaskDao.insert(hisTask)) {
                log.error("插入历史任务失败，实例ID: {}", instanceId);
                return;
            }
            
            // 3. 为每个用户创建历史任务参与者记录
            for (Long userId : userIds) {
                // 查询用户信息获取用户名
                SysUser user = sysUserService.getById(userId);
                
                FlwHisTaskActor hisTaskActor = new FlwHisTaskActor();
                hisTaskActor.setId(flowLongIdGenerator.getId(hisTaskActor.getId()));
                hisTaskActor.setInstanceId(instanceId);
                hisTaskActor.setTaskId(hisTask.getId());
                hisTaskActor.setActorId(userId.toString());
                hisTaskActor.setActorName(user != null ? user.getUsername() : "未知用户");
                hisTaskActor.setActorType(0); // 0表示用户类型
                hisTaskActor.setWeight(6); // 6表示抄送人
                
                if (!hisTaskActorDao.insert(hisTaskActor)) {
                    log.error("插入历史任务参与者失败，用户ID: {}, 任务ID: {}", userId, hisTask.getId());
                }
            }
            
            log.info("成功创建抄送任务，实例ID: {}, 任务ID: {}, 抄送用户数: {}", 
                    instanceId, hisTask.getId(), userIds.size());
        } catch (Exception e) {
            log.error("创建抄送任务异常，实例ID: {}", instanceId, e);
        }
    }


    
    /**
     * 收集流程实例中实际活动任务的审批人、主管信息和流程发起人
     */
    private void collectAllAssignees(Long instanceId, Set<String> allUserIds) {
        try {
            // 1. 首先获取流程实例信息，收集发起人
            FlwInstance instance = flowLongEngine.queryService().getInstance(instanceId);
            if (instance != null && instance.getCreateId() != null) {
                allUserIds.add(instance.getCreateId());
                log.debug("添加流程发起人: {} (ID: {})", instance.getCreateBy(), instance.getCreateId());
            }
            
            // 2. 使用flowLongEngine获取流程实例中当前活动的任务执行者
            Optional<List<FlwTaskActor>> activeTaskActorsOpt = flowLongEngine.queryService().getActiveTaskActorsByInstanceId(instanceId);
            
            if (!activeTaskActorsOpt.isPresent() || activeTaskActorsOpt.get().isEmpty()) {
                log.warn("流程实例 {} 中没有活动的任务执行者", instanceId);
                return;
            }
            
            List<FlwTaskActor> activeTaskActors = activeTaskActorsOpt.get();
            log.info("流程实例 {} 中找到 {} 个活动任务执行者", instanceId, activeTaskActors.size());
            
            // 收集所有活动任务的执行者ID
            for (FlwTaskActor taskActor : activeTaskActors) {
                log.debug("检查任务执行者: {} (ID: {}, Type: {})", taskActor.getActorName(), taskActor.getActorId(), taskActor.getActorType());
                
                if (taskActor.getActorId() != null && taskActor.getActorType() != null) {
                    // 处理所有类型的执行者，不限制actorType
                    String actorId = taskActor.getActorId();
                    allUserIds.add(actorId);
                    log.debug("添加活动任务执行者: {} (ID: {}, Type: {})", taskActor.getActorName(), actorId, taskActor.getActorType());
                    
                    // 收集该用户的部门主管信息
                    try {
                        Long userId = Long.parseLong(actorId);
                        List<DepartmentHeadVO> departmentHeads = sysDepartmentService.getDepartmentHeadInfo(userId, 1, false);
                        if (departmentHeads != null && !departmentHeads.isEmpty()) {
                            for (DepartmentHeadVO head : departmentHeads) {
                                if (head.getHeadId() != null) {
                                    allUserIds.add(head.getHeadId().toString());
                                    log.debug("添加用户 {} 的部门主管: {} (ID: {})", taskActor.getActorName(), head.getHeadName(), head.getHeadId());
                                }
                            }
                        }
                    } catch (NumberFormatException e) {
                        log.warn("用户ID格式错误，无法获取部门主管信息: {}", actorId);
                    } catch (Exception e) {
                        log.warn("获取用户 {} 的部门主管信息失败: {}", actorId, e.getMessage());
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("收集流程实例 {} 的活动任务执行者失败: {}", instanceId, e.getMessage(), e);
        }
    }
}
